#include <2025Linux.h>
int main(int argc, char *argv[])
{
    // ./01_server_epoll 192.168.72.128 12345
    ARGS_CHECK(argc,3);
    int sockfd = socket(AF_INET,SOCK_STREAM,0);
    ERROR_CHECK(sockfd,-1,"socket");
    int flag = 1;
    int ret = setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&flag,sizeof(flag));
    ERROR_CHECK(ret,-1,"setsockopt");
    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(atoi(argv[2]));
    addr.sin_addr.s_addr = inet_addr(argv[1]);
    ret = bind(sockfd,(struct sockaddr *)&addr, sizeof(addr));
    ERROR_CHECK(ret,-1,"bind");
    ret = listen(sockfd, 10);
    ERROR_CHECK(ret,-1,"listen");

    // 申请和epoll相关的数据结构
    int epfd = epoll_create(1);
    // 设置监听 netfd和stdin
    struct epoll_event events;//记录将来fd就绪之后，往就绪队列里面放的信息
    events.events = EPOLLIN;//说明sockfd是读就绪
    events.data.fd = sockfd; //将来fd就绪之后，把文件描述符填入队列
    epoll_ctl(epfd,EPOLL_CTL_ADD,sockfd,&events);//设置sockfd的监听

    struct epoll_event readyset[1024];//给将来的就绪集合申请空间
    char buf[4096];
    int netfd = -1; // -1 说明阿强死了
    while(1){
        int readynum = epoll_wait(epfd,readyset,1024,-1);
        // 当运行到这一行 说明有就绪的
        for(int i = 0; i < readynum; ++i){
            if(readyset[i].data.fd == sockfd){
                // 有客户端连接，可以调用accept
                netfd = accept(sockfd,NULL,NULL);
                // 加监听
                events.events = EPOLLIN;
                events.data.fd = STDIN_FILENO;
                epoll_ctl(epfd,EPOLL_CTL_ADD,STDIN_FILENO,&events);
                events.events = EPOLLIN;
                events.data.fd = netfd;
                epoll_ctl(epfd,EPOLL_CTL_ADD,netfd,&events);
                // 移除sockfd的监听
                epoll_ctl(epfd,EPOLL_CTL_DEL,sockfd,NULL);//移除监听第四个参数可以写NULL
            }
            else if(readyset[i].data.fd == STDIN_FILENO){
                // azhen说话了
                memset(buf,0,sizeof(buf));
                read(STDIN_FILENO,buf,sizeof(buf));
                send(netfd,buf,strlen(buf),0);
            }
            else if(readyset[i].data.fd == netfd){
                // aqiang说活了 or  aqiang断开了
                memset(buf,0,sizeof(buf));
                ssize_t sret = recv(netfd,buf,sizeof(buf),0);
                if(sret == 0){
                    // aqiang断开了
                    epoll_ctl(epfd,EPOLL_CTL_DEL,STDIN_FILENO,NULL); 
                    epoll_ctl(epfd,EPOLL_CTL_DEL,netfd,NULL); 
                    events.events = EPOLLIN;
                    events.data.fd = sockfd;
                    epoll_ctl(epfd,EPOLL_CTL_ADD,sockfd,&events);
                    close(netfd);
                    netfd = -1;
                    printf("wohuihaohaode!\n");
                    continue;
                }
                // aqiang发消息了
                printf("buf = %s\n", buf);
            }
        }
    }
    return 0;
}

